//
//  Object.cpp
//  Simulation
//
//  Created by Christopher Kemsley on 2/27/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#include "Object.hpp"
#include "Exception.hpp"


NamespaceBegin




Object :: Object ()
:	myContext ( ObjectContext :: currentContext() )
	{
	myContext . addObject ( this ) ;
	}

Object :: ~Object ()
	{
	myContext . removeObject ( this ) ;
	}





ObjectContext :: ObjectContext ()
:	mObjects ()
,	mIsOpen ( false )
	{
	
	}
ObjectContext :: ~ObjectContext ()
	{
	if ( mIsOpen ) close () ;
	
	Objects				objs	=	mObjects ;
	Objects::iterator	here	=	objs.begin() ;
	Objects::iterator	end		=	objs.end() ;
	while ( here != end )
		{
		Object * o = *(here++) ;
		// Check in case another object deleted it
		// during its deallocation
		if ( containsObject(o) )
			delete o ;
		}
	}

ObjectContext&	ObjectContext :: currentContext ()
	{
	if ( contextStack().size() == 0 )
		ThrowException ( "ObjectContext" , "There are no active object management contexts" , __FILE__,__LINE__ ) ;
	return * contextStack().back() ;
	}

void	ObjectContext :: open ()
	{
	if ( mIsOpen )
		ThrowException ( "ObjectContext" , "Tried to open already-open context" , __FILE__,__LINE__ ) ;
	
	mIsOpen = true ;
	contextStack() . push_back ( this ) ;
	}
void	ObjectContext :: close ()
	{
	if ( ! mIsOpen )
		ThrowException ( "ObjectContext" , "Tried to close already-closed context" , __FILE__,__LINE__ ) ;
	
	mIsOpen = false ;
	Contexts::iterator	here	=	contextStack().begin() ;
	Contexts::iterator	end		=	contextStack().end() ;
	while ( here != end )
		{
		ObjectContext * c = *here ;
		if ( c == this )
			{
			contextStack() . erase ( here ) ;
			break ;
			}
		else
			{
			here ++ ;
			}
		}
	
	if ( here == end )
		ThrowException ( "ObjectContext" , "Internal inconsistency: node says it's open, but not in the stack" , __FILE__,__LINE__ ) ;
	}



void	ObjectContext :: addObject		( Object * object )
	{
	mObjects . insert ( object ) ;
	}
void	ObjectContext :: removeObject	( Object * object )
	{
	mObjects . erase ( object ) ;
	}
bool	ObjectContext :: containsObject	( Object * object )
	{
	return mObjects.find(object) != mObjects.end() ;
	}


std::vector<ObjectContext*>&	ObjectContext :: contextStack ()
	{
	static std::vector<ObjectContext*> s ;
	return s ;
	}






NamespaceEnd
